/*
 ------------------------------------------------------------------------------
 Copyright (C) 2006-2007 Team Blur.

 This file is part of the Quantum Engine source code.

 The Quantum Engine source code is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License as published by
 the Free Software Foundation; either version 2 of the License, or (at your
 option) any later version.

 The Quantum Engine source code is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 more details.

 You should have received a copy of the GNU General Public License along with
 the Quantum Engine source code; if not, write to the Free Software Foundation, Inc.,
 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 ------------------------------------------------------------------------------
*/


#ifndef __FRAMEWORK_COLLISION_H__
#define __FRAMEWORK_COLLISION_H__


#define CM_MAX_TRACE_DISTANCE		2097152.0f	// Max trace distance in game units

#define CM_CLIP_EPSILON				0.125f		// Always stay this distance away from any plane
#define CM_BOX_EPSILON				1.0f		// Should always be larger than clip epsilon

// Content masks
#define	MASK_ALL					(-1)
#define	MASK_SOLID					(CONTENT_SOLID)
#define	MASK_PLAYERSOLID			(CONTENT_SOLID|CONTENT_PLAYERCLIP|CONTENT_BODY)
#define MASK_VEHICLESOLID			(CONTENT_SOLID|CONTENT_VEHICLECLIP|CONTENT_BODY)
#define MASK_MOVEABLESOLID			(CONTENT_SOLID|CONTENT_MOVEABLECLIP|CONTENT_BODY)
#define	MASK_DEADSOLID				(CONTENT_SOLID|CONTENT_PLAYERCLIP)
#define	MASK_OPAQUE					(CONTENT_OPAQUE)
#define MASK_TRANSLUCENT			(CONTENT_TRANSLUCENT)
#define	MASK_LIQUID					(CONTENT_WATER|CONTENT_SLIME|CONTENT_LAVA)
#define	MASK_SHOT					(CONTENT_SOLID|CONTENT_BODY|CONTENT_CORPSE)
#define MASK_MISSILESHOT			(CONTENT_SOLID|CONTENT_MISSILECLIP|CONTENT_BODY|CONTENT_CORPSE)

typedef struct clipModel_s			clipModel_t;

typedef struct {
	const char *			material;			// Surface material

	int						surfaceFlags;		// Surface flags
	int						contentFlags;		// Contents at other side of surface

	odPlane					plane;				// Surface plane, only valid if allInside == false

	int						entityNum;			// Entity the surface is a part of (not set by CM_* functions)
} contactInfo_t;

typedef struct {
	bool					allInside;			// If true, the start and end points were inside a volume
	bool					startInside;		// If true, the start point was inside a volume

	float					fraction;			// Fraction of trace completed, 1.0 == didn't hit anything
	odVec3					endPos;				// Final position

	contactInfo_t			c;					// Contact information, only valid if fraction < 1.0
} trace_t;

typedef struct {
	int						areas[2];			// Areas connected by the portal

	bool					open;				// Portal state
} areaPortal_t;

/*
 ==============================================================================

 FUNCTIONS EXPORTED BY THE ENGINE

 ==============================================================================
*/

typedef struct {
	// Loads and prepares the given map for collision detection
	void					(*LoadMap)(const char *name);

	// Loads and registers the given model
	clipModel_t *			(*RegisterModel)(const char *name);

	// Sets up a box model for collision detection
	clipModel_t *			(*SetupBoxModel)(const odBounds &bounds, int surfaceFlags, int contentFlags);

	// Creates a new instance of the given model, or returns an existing one.
	// This must be used when doing collision detection on a dynamic model,
	// because the clip model must be reconstructed every frame to match the
	// animated geometry for every entity using the given model.
	// The joints parameter can be NULL, in which case the model will be
	// instantiated in its default pose.
	clipModel_t *			(*InstantiateDynamicModel)(clipModel_t *model, int entityNum, odJointMat *joints);

	// Returns the contents of all the brushes and surfaces of the given model
	// OR'ed together
	int						(*GetModelContents)(clipModel_t *model);

	// Returns the bounds of the given model
	void					(*GetModelBounds)(clipModel_t *model, odBounds &bounds);

	// Returns the contents of the world or model volumes contacted by the
	// given point (bounds == 0) or box (bounds != 0), or 0 if in empty space
	int						(*Contents)(const odVec3 &point, const odBounds &bounds, int contentMask, clipModel_t *model, const odVec3 &modelOrigin, const odMat3 &modelAxis);

	// Performs a point (bounds == 0) or box (bounds != 0) trace through the
	// world or a model.
	// A trace with start == end will actually perform a position test.
	trace_t					(*Trace)(const odVec3 &start, const odVec3 &end, const odBounds &bounds, int contentMask, clipModel_t *model, const odVec3 &modelOrigin, const odMat3 &modelAxis);

	// Returns the leaf contacted by the given point
	int						(*PointInLeaf)(const odVec3 &point);

	// Returns the cluster of the given leaf
	int						(*LeafCluster)(int leafNum);

	// Returns the area of the given leaf
	int						(*LeafArea)(int leafNum);

	// Returns true if a portal sky can be seen from the given leaf
	bool					(*LeafCanSeePortalSky)(int leafNum);

	// Returns the PVS for the given cluster
	const byte *			(*ClusterPVS)(int clusterNum);

	// Returns true if point is in the PVS of the given cluster.
	// Also considers area connections.
	bool					(*PointInPVS)(const odVec3 &point, int clusterNum, int areaNum);

	// Returns true if bounds are in the PVS of the given cluster.
	// Also considers area connections.
	bool					(*BoundsInPVS)(const odBounds &bounds, int clusterNum, int areaNum);

	// Returns the number of portals in the current map
	int						(*NumPortals)(void);

	// Returns the portal contacted by the given bounds, or -1 if no portal is
	// contacted
	int						(*FindPortal)(const odBounds &bounds);

	// Sets the state of the given portal
	void					(*SetPortalState)(int portalNum, bool open);

	// Gets the state of the given portal
	bool					(*GetPortalState)(int portalNum);

	// Writes a bit vector of all the portals that are in an opened state.
	// Returns the number of bytes needed to hold all the bits.
	int						(*WritePortalBits)(byte *buffer);

	// Returns true if the given areas are connected
	bool					(*AreasAreConnected)(int areaNum1, int areaNum2);

	// Returns the number of areas in the current map
	int						(*NumAreas)(void);

	// Returns the area contacted by the given point
	int						(*PointInArea)(const odVec3 &point);

	// Fills a list of all the areas contacted by the given bounds.
	// Returns the number of areas in the list.
	int						(*BoundsInAreas)(const odBounds &bounds, int *areas, int maxAreas);

	// Returns the number of portals in the given area
	int						(*NumPortalsInArea)(int areaNum);

	// Returns a portal from the given area
	void					(*GetPortalFromArea)(int areaNum, int portalNum, areaPortal_t *areaPortal);

	// Writes a bit vector of all the areas that are in the same flood as the
	// area parameter.
	// Returns the number of bytes needed to hold all the bits.
	int						(*WriteAreaBits)(int areaNum, byte *buffer);
} odCollision_t;


#endif	// __FRAMEWORK_COLLISION_H__
